﻿using System;
using System.Text;
using GeoAPI.Geometries;

namespace NetTopologySuite.GeometriesGraph
{
	public class TopologyLocation
	{
		public TopologyLocation(Location[] location)
		{
			this.Init(location.Length);
		}

		public TopologyLocation(Location on, Location left, Location right)
		{
			this.Init(3);
			this._location[0] = on;
			this._location[1] = left;
			this._location[2] = right;
		}

		public TopologyLocation(Location on)
		{
			this.Init(1);
			this._location[0] = on;
		}

		public TopologyLocation(TopologyLocation gl)
		{
			if (gl == null)
			{
				throw new System.ArgumentNullException("gl", "null topology location specified");
			}
			this.Init(gl._location.Length);
			for (int i = 0; i < this._location.Length; i++)
			{
				this._location[i] = gl._location[i];
			}
		}

		private void Init(int size)
		{
			this._location = new Location[size];
			this.SetAllLocations(Location.Null);
		}

		public Location Get(Positions posIndex)
		{
			if (posIndex < (Positions)this._location.Length)
			{
				return this._location[(int)posIndex];
			}
			return Location.Null;
		}

		public Location this[Positions posIndex]
		{
			get
			{
				return this.Get(posIndex);
			}
			set
			{
				this.SetLocation(posIndex, value);
			}
		}

		public bool IsNull
		{
			get
			{
				for (int i = 0; i < this._location.Length; i++)
				{
					if (this._location[i] != Location.Null)
					{
						return false;
					}
				}
				return true;
			}
		}

		public bool IsAnyNull
		{
			get
			{
				for (int i = 0; i < this._location.Length; i++)
				{
					if (this._location[i] == Location.Null)
					{
						return true;
					}
				}
				return false;
			}
		}

		public bool IsEqualOnSide(TopologyLocation le, int locIndex)
		{
			return this._location[locIndex] == le._location[locIndex];
		}

		public bool IsArea
		{
			get
			{
				return this._location.Length > 1;
			}
		}

		public bool IsLine
		{
			get
			{
				return this._location.Length == 1;
			}
		}

		public void Flip()
		{
			if (this._location.Length <= 1)
			{
				return;
			}
			Location location = this._location[1];
			this._location[1] = this._location[2];
			this._location[2] = location;
		}

		public void SetAllLocations(Location locValue)
		{
			for (int i = 0; i < this._location.Length; i++)
			{
				this._location[i] = locValue;
			}
		}

		public void SetAllLocationsIfNull(Location locValue)
		{
			for (int i = 0; i < this._location.Length; i++)
			{
				if (this._location[i] == Location.Null)
				{
					this._location[i] = locValue;
				}
			}
		}

		public void SetLocation(Positions locIndex, Location locValue)
		{
			this._location[(int)locIndex] = locValue;
		}

		public void SetLocation(Location locValue)
		{
			this.SetLocation(Positions.On, locValue);
		}

		public Location[] GetLocations()
		{
			return this._location;
		}

		public void SetLocations(Location on, Location left, Location right)
		{
			this._location[0] = on;
			this._location[1] = left;
			this._location[2] = right;
		}

		public void SetLocations(TopologyLocation gl)
		{
			for (int i = 0; i < gl._location.Length; i++)
			{
				this._location[i] = gl._location[i];
			}
		}

		public bool AllPositionsEqual(Location loc)
		{
			for (int i = 0; i < this._location.Length; i++)
			{
				if (this._location[i] != loc)
				{
					return false;
				}
			}
			return true;
		}

		public void Merge(TopologyLocation gl)
		{
			if (gl._location.Length > this._location.Length)
			{
				this._location = new Location[]
				{
					this._location[0],
					Location.Null,
					Location.Null
				};
			}
			for (int i = 0; i < this._location.Length; i++)
			{
				if (this._location[i] == Location.Null && i < gl._location.Length)
				{
					this._location[i] = gl._location[i];
				}
			}
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (this._location.Length > 1)
			{
				stringBuilder.Append(LocationUtility.ToLocationSymbol(this._location[1]));
			}
			stringBuilder.Append(LocationUtility.ToLocationSymbol(this._location[0]));
			if (this._location.Length > 1)
			{
				stringBuilder.Append(LocationUtility.ToLocationSymbol(this._location[2]));
			}
			return stringBuilder.ToString();
		}

		private Location[] _location;
	}
}
